package cn.bytest.netty;

import cn.bytets.rpc.api.message.Request;
import io.netty.channel.Channel;

import java.net.InetSocketAddress;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class NettyChannel implements cn.bytets.rpc.api.Channel {

    private static final ConcurrentMap<Channel, NettyChannel> CHANNEL_MAP = new ConcurrentHashMap<Channel, NettyChannel>();

    private Channel channel;

    private Request request;

    private String host;

    private int port;

    private volatile boolean closed = false;



    public NettyChannel(Channel ch){
        this(ch,null);
    }

    public NettyChannel(Channel ch,Request data){
        this(ch,data,null,0);
    }
    public NettyChannel(Channel ch,
                        Request data,
                        String host,
                        int port){
        this.channel = ch;
        this.request = data;
        this.host = host;
        this.port = port;
    }

    public static NettyChannel getOrAddChannel(Channel ch) {
        if (ch == null) {
            return null;
        }
        NettyChannel ret = CHANNEL_MAP.get(ch);
        if (ret == null) {
            NettyChannel nettyChannel = new NettyChannel(ch);
            if (ch.isActive()) {
                ret = CHANNEL_MAP.putIfAbsent(ch, nettyChannel);
            }
            if (ret == null) {
                ret = nettyChannel;
            }
        }
        return ret;
    }
    public static NettyChannel getOrAddChannel(Channel ch,Request request) {
        NettyChannel ret = getOrAddChannel(ch);
        ret.request = request;
        return ret;
    }
    public static NettyChannel getOrAddChannel(Channel ch,Request request,String host,int port) {
        NettyChannel ret = getOrAddChannel(ch);
        ret.request = request;
        ret.host = host;
        ret.port = port;
        return ret;
    }

    public static NettyChannel removeChannelIfDisconnected(Channel ch){
        return  CHANNEL_MAP.remove(ch);
    }
    public InetSocketAddress getLocalAddress() {
        return (InetSocketAddress) channel.localAddress();
    }
    public InetSocketAddress getRemoteAddress() {
        return (InetSocketAddress) channel.remoteAddress();
    }

    public void close(){
        if (isClosed()){
            return;
        }
        removeChannelIfDisconnected(channel);

        if(null!=channel&&channel.isActive()){
            channel.close();
            this.closed = true;
        }
    }

    /**
     * is closed.
     *
     * @return closed
     */
    @Override
    public boolean isClosed() {
        if (null!=channel){
            closed = !channel.isActive();
        }
        return closed;
    }

    public static String toAddressString(InetSocketAddress address) {
        return address.getAddress().getHostAddress() + ":" + address.getPort();
    }

    public void send(Object msg){
        if (null!=channel&&channel.isActive()) {
            channel.writeAndFlush(msg);
        } else {
            throw new NullPointerException("发送消息:"+msg+",但是客户端为空");
        }
    }

    public void setRequest(Request request) {
        this.request = request;
    }

    public Request getRequest(){
        return this.request;
    }

    public String getHost() {
        return host;
    }

    public int getPort() {
        return port;
    }
}
